#pragma once

#include <sys/types.h>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <sys/wait.h>
#include "Task.hpp"


// 先描述
class PipeNode
{
public:
    PipeNode(int wt, pid_t id) : _wt(wt), _id(id) {}

    int get_wt()
    {
        return _wt;
    }

    pid_t get_id()
    {
        return _id;
    }


private:
    int _wt;   // 父进程的写端
    pid_t _id; // 子进程pid
};

// 再组织
class PoolTable
{
public:
    PoolTable(size_t amount = 5) : _amount(amount) {}

    size_t get_amount()
    {
        return _amount;
    }

    int get_wt(int i)
    {
        if (i < 0 || i >= _amount)
            return -1;
        return _table[i].get_wt();
    }

    pid_t get_id(int i)
    {
        if (i < 0 || i >= _amount)
            return -1;
        return _table[i].get_id();
    }

    void push(PipeNode pipenode)
    {
        _table.push_back(pipenode);
    }

    void debug()
    {
        auto it = _table.begin();
        int i = 1;
        while (it != _table.end())
        {
            std::cout << "name" << i++ << "-" << (*it).get_wt() << "-" << (*it).get_id() << std::endl;
            ++it;
        }
    }


private:
    std::vector<PipeNode> _table;
    size_t _amount;
};

// 进程池
class ProcessPool
{
public:
    ProcessPool(size_t amount = 5) : _pool(amount) {}

    void create()
    {
        for (int i = 0; i < _pool.get_amount(); ++i)
        {
            int pipe_id[2] = {0};
            int ret = pipe(pipe_id);

            if (ret < 0)
            {
                perror("pipe fail\n");
                exit(1);
            }

            pid_t pid = fork();
            if (pid == 0)
            {
                // 子进程
                close(pipe_id[1]);
                child_read(pipe_id[0]);
                close(pipe_id[0]);
                exit(0);
            }

            // 父进程
            close(pipe_id[0]);
            _pool.push(PipeNode(pipe_id[1], pid));
            
        }
    }

    // 子进程执行任务 记得！！！大坑点！！！
    //不能先  if (ret != sizeof(int))    
    // void child_read(int rd)
    // {
    //     while (1)
    //     {
    //         int task = 0;
    //         ssize_t ret = read(rd, &task, sizeof(task));
    //         if (ret != sizeof(int))
    //             continue;
    //         else if (ret == 0)
    //         {
    //             std::cout << "子进程[" << getpid() << "]退出" << std::endl;
    //             break;
    //         }
    //         else if(ret < 0)
    //         {
    //             std::cout << "读取错误" << std::endl;
    //             break;
    //         }
    //         else
    //         { 
    //             // 调用执行任务函数
    //             printf("我是子进程%d:我在执行任务 %d\n", getpid(), task);
    //         }
    //     }
    // }
    void child_read(int rd)
    {
        while (true)
        {
            int task = 0;
            ssize_t ret = read(rd, &task, sizeof(task));
            if(ret > 0)
            {
                if(ret != sizeof(task))
                    continue;

                // 调用执行任务函数
                std::cout << "我是进程" << getpid() - getppid() << std::endl;
                task_manage.execute(task);
            }

            else if (ret == 0)
            {
                std::cout << "子进程[" << getpid() << "]退出" << std::endl;
                break;
            }
            else 
            {
                std::cout << "读取错误" << std::endl;
                break;
            }
       
        }
    }

    //注册任务
    void Register(task_t task)
    {
        task_manage.push(task);
    }

    // 父进程布置任务
    void parent_task()
    {
        // 选择子进程
        int process = order++ % _pool.get_amount();

        // 选择任务
        //srand (time(NULL));  不行？
        int i = task_manage.choose();

        // 布置任务
        write(_pool.get_wt(process), &i, sizeof(int));
    }


    void Stop()
    {
        Close();
        Wait();
        std::cout << "子进程已全部关闭" << std::endl;
    }

    // 父进程关闭写端
    void Close()
    {
        for (int i = 0; i < _pool.get_amount(); ++i)
        {
            int ret = close(_pool.get_wt(i));
            // if (ret < 0)
            //     perror("关闭失败");
            // else
            //     printf("关闭成功\n");
        }
    }

    void Wait()
    {
        for (int i = 0; i < _pool.get_amount(); ++i)
        {
            //int status = 0;
            waitpid(_pool.get_id(i), NULL, 0);
            // printf("子进程退出码：%d, 子进程退出信号:%d\n", (status >> 8) & 0xff, status & 0x7f);
        }
    }

    void debug()
    {
        _pool.debug();
    }


private:
    PoolTable _pool;
    int order = 0;
    TaskManage task_manage;
};